package org.dreamwork.hyacinth;

import org.dreamwork.misc.MimeTypeManager;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.*;
import javax.mail.util.ByteArrayDataSource;
import java.io.*;
import java.util.*;

/**
 * Created by IntelliJ IDEA.
 * User: seth
 * Date: 2010-4-25
 * Time: 23:36:45
 */
public class Mail {
    private String subject;
    private String from;
    private List<String> to = new ArrayList<String> ();
    private List<String> cc = new ArrayList<String> ();
    private List<String> bcc = new ArrayList<String> ();
    private MailType type = MailType.Plain;
    private CharSequence body;
    private Map<String, Object> attachments = new HashMap<String, Object> ();
    private boolean debug;

    public String getSubject () {
        return subject;
    }

    public void setSubject (String subject) {
        this.subject = subject;
    }

    public String getFrom () {
        return from;
    }

    public void setFrom (String from) {
        this.from = from;
    }

    public List<String> getTo () {
        return to;
    }

    public void setTo (List<String> to) {
        this.to = to;
    }

    public void addTo (String to) {
        this.to.add (to);
    }

    public List<String> getCC () {
        return cc;
    }

    public void setCC (List<String> cc) {
        this.cc = cc;
    }

    public void addCC (String cc) {
        this.cc.add (cc);
    }

    public List<String> getBCC () {
        return bcc;
    }

    public void setBCC (List<String> bcc) {
        this.bcc = bcc;
    }

    public void addBCC (String bcc) {
        this.bcc.add (bcc);
    }

    public MailType getType () {
        return type;
    }

    public void setType (MailType type) {
        this.type = type;
    }

    public CharSequence getBody () {
        return body;
    }

    public void setBody (CharSequence body) {
        this.body = body;
    }

    public Map<String, Object> getAttachments () {
        return attachments;
    }

    public void setAttachments (Map<String, Object> attachments) {
        this.attachments = attachments;
    }

    public void addAttachment (Object attachment) {
        String name = "attachment-" + attachments.size ();
        this.attachments.put (name, attachment);
    }

    public void addAttachement (String name, Object attachment) {
        attachments.put (name, attachment);
    }

    public boolean isDebug () {
        return debug;
    }

    public void setDebug (boolean debug) {
        this.debug = debug;
    }

    protected Message buildMessage (Session session) throws MessagingException, IOException {
	    Message msg = new MimeMessage (session);
	    if (from != null)
		msg.setFrom(new InternetAddress (from));
	    else
		msg.setFrom();

        StringBuilder builder = new StringBuilder ();
        for (String s : to) {
            if (builder.length () > 0) builder.append (',');
            builder.append (s);
        }
	    msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(builder.toString (), false));
	    if (cc != null) {
            builder.setLength (0);
            for (String s : cc) {
                if (builder.length () > 0) builder.append (',');
                builder.append (s);
            }
		    msg.setRecipients(Message.RecipientType.CC,InternetAddress.parse(builder.toString (), false));
        }
	    if (bcc != null) {
            builder.setLength (0);
            for (String s : bcc) {
                if (builder.length () > 0) builder.append (',');
                builder.append (s);
            }
		    msg.setRecipients(Message.RecipientType.BCC, InternetAddress.parse(builder.toString (), false));
        }
	    msg.setSubject(subject);

        if (type == MailType.Plain) msg.setText (body.toString ());
        else {
            MimeMultipart mmp = new MimeMultipart ();
            MimeBodyPart main = new MimeBodyPart ();
            if (type == MailType.Html)
                main.setContent (body.toString (), "text/html;charset=utf-8");
            else
                main.setText (body.toString ());
            mmp.addBodyPart (main);

            for (String key : attachments.keySet ()) {
                Object obj = attachments.get (key);
                MimeBodyPart part = new MimeBodyPart ();
                if (obj instanceof File) {
                    File file = (File) obj;
                    part.attachFile (file);
                } else if (obj instanceof HexAttachment) {
                    HexAttachment ha = (HexAttachment) obj;
                    DataSource ds = new ByteArrayDataSource (ha.getData (), ha.getContentType ());
                    DataHandler handler = new DataHandler (ds);
                    part.setDataHandler (handler);
                } else if (obj instanceof byte[]) {
                    processHexData ((byte[]) obj, part);
                } else {
                    ByteArrayOutputStream baos = new ByteArrayOutputStream ();
                    ObjectOutputStream out = new ObjectOutputStream (baos);
                    out.writeObject (obj);
                    out.flush ();
                    processHexData (baos.toByteArray (), part);
                }
                part.setHeader ("Content-ID", '<' + key + '>');
                mmp.addBodyPart (part);
            }
            msg.setContent (mmp, "text/plain");
        }

	    msg.setHeader("X-Mailer", "Hyacinth v1.0");
	    msg.setSentDate(new Date ());
        return msg;
    }

    private void processHexData (byte[] data, MimeBodyPart part) throws MessagingException {
        DataSource source = new ByteArrayDataSource (data, MimeTypeManager.getType ("bin"));
        DataHandler handler = new DataHandler (source);
        part.setDataHandler (handler);
    }
}